﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PaperRenderingInterfaces;
using DeepZoomPivotConstructor.PivotLib;
using System.ComponentModel.Composition;
using DeepZoomPivotConstructor.VisualLib;
using System.IO;
using PaperPluginUtilities;

namespace CDSParser
{
    /// <summary>
    /// Will render the figures from a single paper in CDS
    /// </summary>
    [Export(typeof(IPaperRender))]
    [PaperRender("CDSFiguresFromOnePaper")]
    public class CDSFiguresFromOnePaper : IPaperRender
    {
        [Import(typeof(IWebAccess))]
        private IWebAccess WebAccessFetcher;

        /// <summary>
        /// Given the CDS paper record number, get the figures associated with it
        /// </summary>
        /// <param name="cdsRecordID"></param>
        /// <returns></returns>
        public IEnumerable<PivotImage> Render(string cdsRecordID)
        {
            ///
            /// Build the URL of the web guy and see if we can't get it back and parse it.
            /// 

            string htmlAccessMARC = "http://cdsweb.cern.ch/record/" + cdsRecordID + "/export/xm";
            var xmlMARC = CDSUtilities.FetchParsedCDSMARKXML(WebAccessFetcher, htmlAccessMARC);
            string htmlAccessDC = "http://cdsweb.cern.ch/record/" + cdsRecordID + "/export/xd";
            var xmlDC = CDSUtilities.FetchParsedCDSDCXML(WebAccessFetcher, htmlAccessDC);

            ///
            /// Get the abstract
            /// 

            var abstractField = from f in xmlMARC.record[0].datafield
                                where f.tag == "520"
                                from sf in f.subfield
                                where sf.code == "a"
                                select sf.Value;
            string caption = abstractField.FirstOrDefault();
            string description;
            if (caption == null || caption.Length == 0)
            {
                description = "No Description or abstract provided";
                caption = "<none>";
            }
            else
            {
                description = "No Description provided - note abstract: " + caption;
            }
            ///
            /// And the date.
            /// 

            var date = Convert.ToDateTime(xmlDC.Items[0].date);

            ///
            /// And the title
            /// 

            var title = (from df in xmlMARC.record[0].datafield
                         where df.tag == "245"
                         from sf in df.subfield
                         where sf.code == "a"
                         select sf.Value).FirstOrDefault();
            if (title == null)
            {
                title = "<no title>";
            }

            ///
            /// Find the figure references. I'm not totally sure what the library of congress is thinking here...
            /// 

            var figsField = from f in xmlMARC.record[0].datafield
                            where f.tag == "856"
                            from sy in f.subfield
                            where sy.code == "y" && sy.Value.Contains("Figure")
                            select new
                            {
                                URL = (from su in f.subfield where su.code=="u" select su.Value).FirstOrDefault(),
                                FigureName = sy.Value
                            };

            var figureOnlyResult = figsField.Where(a => a.URL != null).SelectMany(f => 
                ConverToPivotImages(f.URL, f.FigureName, description)
                .Apply(i => i.Add("Caption", caption))
                .Apply(i => i.Add("Date", date))
                .Apply(i => i.Add("More Information", "CDS Note Page", new Uri("http://cdsweb.cern.ch/record/" + cdsRecordID + "?ln=en")))
                .Apply(i => i.Add("Note Title", title))
                );

            ///
            /// Can we find the full text for a note?
            /// 

            var fullTextNoteNodes = from f in xmlMARC.record[0].datafield
                                    where f.tag == "856"
                                    let ytag = (from st in f.subfield where st.code == "y" select st.Value).FirstOrDefault()
                                    let utag = (from st in f.subfield where st.code == "u" select st.Value).FirstOrDefault()
                                    where ytag != null && utag != null
                                    select new
                                    {
                                        YTag = ytag,
                                        UTag = utag
                                    };
            var fullTextLink = (from ft in fullTextNoteNodes
                               where ft.YTag.ToLower().Contains("fulltext")
                               select ft.UTag).FirstOrDefault();

            if (fullTextLink != null)
            {
                figureOnlyResult = figureOnlyResult.Apply(i => i.Add("More Information", "Note", new Uri(fullTextLink)));
            }

            ///
            /// And if it is published!
            /// 

            var fullTextNotePub = (from f in xmlMARC.record[0].datafield
                                   where f.tag == "856"
                                   from sy in f.subfield
                                   where sy.code == "y"
                                   select (from su in f.subfield where su.code == "u" select su.Value).FirstOrDefault()).FirstOrDefault();


            return figureOnlyResult;
        }

        [Import(typeof(RenderEngineInterfaces.IRenderEngine))]
        private RenderEngineInterfaces.IRenderEngine MyRenderEngine;

        /// <summary>
        /// Given a figure, create a matching pivot image if we can. Return the empty case if we can't.
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        private IEnumerable<PivotImage> ConverToPivotImages(string url, string name, string description)
        {
            Uri u = new Uri(url);
            Visual v = MyRenderEngine.Render(u, forceAsComposableUnit:true);
            if (v != null)
            {
                PivotImage img = new PivotImage(v);
                img.Name = name;
                img.Description = description;

                string ext = Path.GetExtension(u.Segments.Last());
                if (!ext.StartsWith("."))
                {
                    img.Add("Graphics Files", "Figure Graphic", u);
                }
                else
                {
                    img.Add("Graphics Files", ext.Substring(1), u);
                }

                yield return img;
            }
        }

    }
}
